#Anaconda/envs/pysagin python
# -*- coding: utf-8 -*-
'''
device.py
=========

.. module:: device
  :platform: Windows, Linux
  :synopsis: 平台设备

.. moduleauthor:: WangXi

简介
----


版本
----

- 版本 1.0 (2025/03/30): 初始版本

'''

from pysagin.base import Base
from scipy.spatial import KDTree

class Device:
    def __init__(self, name, platform, type, **kwargs):
        self.name = name
        self.type = type
        self.platform:Base = platform
        
class Radio(Device):
    def __init__(self, name, platform, range, **kwargs):
        """无线电台

        Args:
            name (str): 电台命名
            platform (Base): 所部署的平台
            range (float): 无线电台的最大双向传输距离, 单位km
        """
        super().__init__(name, platform, type=self.__class__.__name__, **kwargs)
        self.range = range
        
    def check_access(self, target_radio:"Radio") -> bool:
        distance = Base.calculate_distance(self.platform.get_current_gps(), 
                                           target_radio.platform.get_current_gps())
        if distance <= self.range and distance <= target_radio.range:
            return True
        else:
            return False
        
    def get_current_access_radios(self) -> list["Radio"]:
        raise NotImplementedError("子类必须实现该方法")
        
class RadioFixedAccess(Radio):
    def __init__(self, name, platform, range, **kwargs):
        """
        固定接入型无线电台

        Args:
            name (str): 无线电台名称
            platform (Base): 所部署的平台
            range (float): 无线电台的最大双向传输距离, 单位km
        """
        
        super().__init__(name, platform, range, **kwargs)
        self.access_radios:list[Radio] = []
    
    def add_access_radios(self, access_radios:list[Radio]) -> None:
        self.access_radios.extend(access_radios)
        
    def get_current_access_radios(self) -> list[Radio]:
        current_access_radios = []
        for radio in self.access_radios:
            if self.check_access(radio):
                current_access_radios.append(radio)
        return current_access_radios
        
class RadioRandomAccess(Radio):
    def __init__(self, name, platform, range, max_access_num:int, **kwargs):
        """
        随机接入型无线电台

        Args:
            name (str): 无线电台名称
            platform (Base): 所部署的平台
            range (float): 无线电台的最大双向传输距离, 单位km
            max_access_num (int): 最大接入的无线电台数量, -1表示无限制
        """
        super().__init__(name, platform, range, **kwargs)
        self.pre_access_radios:list[Radio] = []
        self.max_access_num = max_access_num

    def add_pre_access_radios(self, pre_access_radios:list[Radio]) -> None:
        self.pre_access_radios.extend(pre_access_radios)
        
    def get_current_access_radios(self) -> list[Radio]:
        current_access_radios = []
        positions_xyz = []
        for radio in self.pre_access_radios:
            positions_xyz.append(radio.platform.get_gps2xyz())
        kdtree = KDTree(positions_xyz)
        target_xyz = self.platform.get_gps2xyz()
        
        if self.max_access_num == -1:
            indices = kdtree.query_ball_point(target_xyz, r=self.range)
            for i in indices:
                # 即便通过kdtree计算过了两个电台之间的物理距离，但也应增加传输距离的检查（双向距离）
                if self.check_access(self.pre_access_radios[i]):
                    current_access_radios.append(self.pre_access_radios[i])
        else:
            k = self.max_access_num
            _, indices = kdtree.query(target_xyz, k=k)
            if k == 1:
                indices = [indices]
            for i in indices:
                # 即便通过kdtree间接计算过了两个电台之间的物理距离，但也应增加传输距离的检查（双向距离）
                if self.check_access(self.pre_access_radios[i]):
                    current_access_radios.append(self.pre_access_radios[i])
            
        return current_access_radios
            
    
        
    


